/**************
 * File Name: DBBase.cpp
 * Author: Jade@design1online.com
 * Purpose: mysql DBBase class
 **************/
#include "header.h"

/**************
 * Purpose: default constructor, initialize class values
 * Precondition: none
 * Postcondition: none
 **************/
DBBase::DBBase()
{
    //initilize the mysql fields
    sock = NULL;
    row = NULL;
    result = NULL;
    field = NULL;          
}

/**************
 * Purpose: connect to the appropriate DBBase
 * Precondition: host, DBBase, user name and password
 * Postcondition: connected to that DBBase
 **************/
int DBBase::openConnection(const char *host, const char *db,const char *user,const char *pass)
{
    if (sock) //already connected to another DBBase
        disconnect(); //disconnect from that one

    //initilize the socket
    sock = mysql_init(0);

    //something went wrong with the socket
    if (!sock)
        return ERR201;

    //try connecting to the DBBase  
    if (!mysql_real_connect(sock, host, user, pass, db, 0, NULL, CLIENT_MULTI_STATEMENTS))
        return ERR202;

    //successfully connected to the DBBase    
    return SUCCESS;  
}

/**************
 * Purpose: disconnect from the DBBase
 * Precondition: none
 * Postcondition: socket closed
 **************/
bool DBBase::disconnect()
{
    if (sock) //they have a socket open
        mysql_close(sock);

    //release result data
    free(); 

    //DBBase disconnected
    return true;
}

/**************
 * Purpose: free the results from the DBBase query
 * Precondition: none
 * Postcondition: results no longer there
 **************/
bool DBBase::free()
{
    if (result)
    {
        mysql_free_result(result);
        return true;
    }

    return false;
}

/**************
 * Purpose: return the approprite error message
 * Precondition: error code
 * Postcondition: string with the error returned
 **************/
const char *dberror(int errorcode)
{

    //display the appropriate error message for this error    
    switch(errorcode)
    {
        case SUCCESS: return "SUCCESS";
                      break;

        case ERR201: return "201 SOCKET ERROR: SOCKET FAILURE";
                     break;

        case ERR202: return "202 CONNECTION ERROR: CANNOT ACCESS THE SERVER";
                     break;

        case ERR203: return "203 DATABASE ERROR: QUERY FAILED";
                     break;
    }

    return NULL; //no error, return null char
}

/**************
 * Purpose: return the result set of the query
 * Precondition: the query string
 * Postcondition: result set returned (or null)
 **************/
MYSQL_RES *DBBase::query(const char *query)
{        
    //query the DBBase
    if (mysql_query(sock, query)) {
        string queryStr = string(query);
        reportError(queryStr);
        return false;
    }
    //store the results
    //cout << query << endl;
    return mysql_store_result(sock);
}

/**************
 * Purpose: update the DBBase no result returned
 * Precondition: the query string
 * Postcondition: false if failed, true if suceess
 **************/
bool DBBase::updateQuery(string query)
{        
    mysql_query(sock, query.c_str());
    if (*mysql_error(sock)) {
        reportError(query);
        return false;
    } else {
        do {
            /* Process all results */
            /*if (!(result= mysql_store_result(sock))) {
                cout << "Got fatal error processing query" << endl;
                exit(1);
            }
            */
            result= mysql_store_result(sock);
            mysql_free_result(result);
        } while (!mysql_next_result(sock));
    }
    return true; //successful query
}

/**************
 * Purpose: return the result set of the query
 * Precondition: the query string
 * Postcondition: the FIRST result is returned (or null)
 *                will not return multiple rows, only the first
 **************/
char *DBBase::stringQuery(char *query)
{
    //if old results exist, free them
    //free();

    //query the DBBase
    mysql_query(sock,query);

    //store the results
    result = mysql_store_result(sock);

    if (!result)
        return NULL; //no results

    //fetch the row
    row = mysql_fetch_row(result);

    //store the result & convert it to a number
    char *stringResult = row[0];

    //free the results
    free();

    return stringResult;

}

/**************
 * Purpose: return the result set of the query
 * Precondition: the query string
 * Postcondition: the FIRST result is returned (or null)
 *                will not return multiple rows, only the first
 **************/
int DBBase::intQuery(char *query)
{        
    //query the DBBase
    mysql_query(sock,query);

    //store the results
    result = mysql_store_result(sock);

    if (!result)
        return -1; //no results

    //fetch the row
    row = mysql_fetch_row(result);

    //store the result & convert it to a number
    int id = atoi(row[0]);

    //free the results
    free();

    return id; //return the id number

}

/**************
 * Purpose: return the result set of the query
 * Precondition: the query string
 * Postcondition: the FIRST result is returned (or null)
 *                will not return multiple rows, only the first
 **************/
bool DBBase::boolQuery(char *query)
{

    //query the DBBase
    mysql_query(sock, query);

    //store the results
    result = mysql_store_result(sock);

    return (bool)row[0];

}

void DBBase::reportError(string& query)
{
    std::cout << mysql_errno(sock) <<'\t';
    std::cout << mysql_error(sock) <<endl;
    std::cout << query << endl;
    exit(1);
}

